package com.foton.logistic.base;


import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.multidex.MultiDex;
import android.support.multidex.MultiDexApplication;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.DistanceUtil;
import com.foton.logistic.R;
import com.foton.logistic.daemon.DaemonEnv;
import com.foton.logistic.daemon.KeepLiveActivity;
import com.foton.logistic.daemon.KeepLiveManager;
import com.foton.logistic.daemon.TraceServiceImpl;
import com.foton.logistic.listener.IOnResultListener;
import com.foton.logistic.model.GPSEntity;
import com.foton.logistic.model.order.LocalOrderEntity;
import com.foton.logistic.model.order.LocationEntity;
import com.foton.logistic.model.order.OrderEntity;
import com.foton.logistic.service.LocationService;
import com.foton.logistic.task.DispatchTask;
import com.foton.logistic.task.ShowDialogTask;
import com.foton.logistic.task.TaskConstant;
import com.foton.logistic.util.BaseConstant;
import com.foton.logistic.util.BroadcastUtil;
import com.foton.logistic.util.LocationUtil;
import com.foton.logistic.util.OptionUtil;
import com.foton.logistic.util.SharedUtil;
import com.foton.logistic.util.TimeUtil;
import com.foton.logistic.util.image.fresco.FrescoUtils;
import com.foton.logistic.util.net.HttpUtil;
import com.foton.logistic.util.tool.FileUtil;
import com.foton.logistic.util.tool.LogUtil;
import com.foton.logistic.util.tool.StringUtil;
import com.umeng.analytics.MobclickAgent;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * v1.2.9 版保存
 */
public class SaveBaseApplication19 extends MultiDexApplication {
    private static SaveBaseApplication19 baseApplication;
    private String processName = "";
    public static String PACKAGE_NAME;
    public LocationUtil locationUtil;
    public static LocationClient mLocClient;
    public static int LOCTIME = 30000;//定位周期
    //外出服务轨迹记录
    AlarmManager alarms;
    PendingIntent pendingIntent;
    public boolean isOutService = false;
    public LocalOrderEntity localOrderEntity;
    public LocationService locationService;
    public static long lastLocTime = 0;
    //result 0默认值，1成功，2超出20米，3gps模式下速度为0, 4未开始或者已停止, 5限制处理
    private final double defaultLat = 39.915378;
    private final double defaultLng = 116.402831;
    private boolean isOnTrimMemory = false;

    @Override
    public void onCreate() {
        super.onCreate();
//        baseApplication = this;
        PACKAGE_NAME = getPackageName();
        BaseConstant.initDebug();
        BaseConstant.initImagePath(this);
        baseApplication = this;
        init();
    }

    @Override
    public void onTerminate() {
        // 程序终止的时候执行
        LogUtil.e("-----onTerminate----");
        if (BaseConstant.LOGING)
            FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                    " app终止：onTerminate", true);
        super.onTerminate();
    }

    @Override
    public void onLowMemory() {
        // 低内存的时候执行
        LogUtil.e("-----onLowMemory----");
        super.onLowMemory();
    }
    @Override
    public void onTrimMemory(int level) {
        // 程序在内存清理的时候执行
        LogUtil.e("-----onTrimMemory----" + level);
        if (level==TRIM_MEMORY_RUNNING_MODERATE){
            //表示应用程序正常运行，并且不会被杀掉
            if (BaseConstant.LOGING)
                FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                        " APP正常运行：onTrimMemory="+level, true);
//            isOnTrimMemory = false;
        }else if (level==TRIM_MEMORY_RUNNING_LOW){
            //表示应用程序正常运行，并且不会被杀掉
            if (BaseConstant.LOGING)
                FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                        " APP正常运行：onTrimMemory="+level, true);
//            isOnTrimMemory = false;
        }else if (level==TRIM_MEMORY_RUNNING_CRITICAL){
            //表示应用程序仍然正常运行，但是系统已经根据LRU缓存规则杀掉了大部分缓存的进程了
            if (BaseConstant.LOGING)
                FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                        " APP正常运行：onTrimMemory="+level, true);
//            isOnTrimMemory = false;
        }else if (level==TRIM_MEMORY_UI_HIDDEN){
            //界面隐藏
            if (BaseConstant.LOGING)
                FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                        " APP进入后台，界面隐藏：onTrimMemory="+level, true);
            isOnTrimMemory = true;
        }else if (level==TRIM_MEMORY_BACKGROUND){
            //表示手机目前内存已经很低了，系统准备开始根据LRU缓存来清理进程
            isOnTrimMemory = true;
        }else if (level==TRIM_MEMORY_MODERATE){
            //表示手机目前内存已经很低了，并且我们的程序处于LRU缓存列表的中间位置
            isOnTrimMemory = true;
        }else if (level==TRIM_MEMORY_COMPLETE){
            //表示手机目前内存已经很低了，并且我们的程序处于LRU缓存列表的最边缘位置
            isOnTrimMemory = true;
            if (BaseConstant.LOGING)
                FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                        " 手机目前内存已经很低了，并且我们的程序处于LRU缓存列表的最边缘位置：onTrimMemory="+level, true);
           /* OrderConditionEntity orderConditionEntity=new OrderConditionEntity();
            orderConditionEntity.setOrderId(SharedUtil.getLocalOrder(getBaseContext()));
            orderConditionEntity.setTime(TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss"));
            orderConditionEntity.setType("6");
            orderConditionEntity.setAddress(SharedUtil.getAddress(getBaseContext()));
            orderConditionEntity.setLat(SharedUtil.getLat(getBaseContext()));
            orderConditionEntity.setLng(SharedUtil.getLng(getBaseContext()));*/

        }
        super.onTrimMemory(level);
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        attach(base);
    }

    private void init() {

        processName = OptionUtil.getProcessName(this, android.os.Process.myPid());
        if (processName != null) {
            boolean defaultProcess = processName.equals(getPackageName());
            if (defaultProcess) {
                initAppForMainProcess();
            } else if (processName.contains(":watch")) {
                initAppForLiveProcess();
            }
        }
        isOnTrimMemory = false;
    }

    private void initAppForMainProcess() {

        if (BaseConstant.IS_KEEP_LIVE){
            LogUtil.e("--------------DaemonEnv.initialize--------------");
            DaemonEnv.initialize(this, TraceServiceImpl.class, DaemonEnv.DEFAULT_WAKE_UP_INTERVAL);
        }
        FrescoUtils.init(this);
        MobclickAgent.setDebugMode(false);
        SDKInitializer.initialize(this);
        KeepLiveManager.getInstance().startKeepLiveService();
        KeepLiveManager.getInstance().addAccount();
        reInit();
        startOut();
    }

    private void initAppForLiveProcess() {
        if (BaseConstant.IS_KEEP_LIVE){
            LogUtil.e("--------------DaemonEnv.initialize--------------");
            DaemonEnv.initialize(this, TraceServiceImpl.class, DaemonEnv.DEFAULT_WAKE_UP_INTERVAL);
        }
    }

    public void reInit(){
        LogUtil.e("-----locationUtil----   reInit");
        locationUtil = new LocationUtil(this, myLocationListener);
    }


    private void attach(Context base) {
        processName = OptionUtil.getProcessName(this, android.os.Process.myPid());
        if (processName != null) {
            boolean defaultProcess = processName.equals(getPackageName());
            if (defaultProcess) {
                MultiDex.install(base);
//                startKeepLiveService();
            } else if (processName.contains(":watch")) {

            }
        }
    }

    public void startKeepLiveService() {
        try {
            LogUtil.e("isOnTrimMemory= " + isOnTrimMemory);
            if (isOnTrimMemory){
                reInit();
                startOut();
                isOnTrimMemory = false;
            }
            if (BaseConstant.IS_KEEP_LIVE){
                startService(new Intent(this, TraceServiceImpl.class));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void startKeepLiveActivity() {
        try {
            Intent intent = new Intent(this, KeepLiveActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static SaveBaseApplication19 self() {
        return baseApplication;
    }


    public int location(int locTime) {
        if (locationUtil!=null)
            return locationUtil.location("" + locTime);
        return -1;
    }

    public void stopLocation() {
        if (locationUtil!=null)
            locationUtil.stopLocation();
    }

    /**
     * 定位SDK监听函数
     * <p>
     * <p>定位逻辑:</p>
     * <p>如果开启定位，定位成功，当(是否已经开始上传)isOutService = true && (订单实体)orderEntity不为空时
     * 并且(上一次上传成功的时间)OrderTimer>0,并且当前时间减去OrderTimer大于半个小时(ShareUtil.getRetryTime)会上传轨迹
     * （每半个小时上传一次轨迹）</p>
     * <p>
     * <p>上传轨迹失败逻辑:</p>
     * <p>当上传轨迹失败时,会在五分钟延时后重试上传轨迹(ShareUtil.getRetryTime)。
     * 如果当重试后成功,则将重试时间重置为半个小时(上传轨迹逻辑:每半个小时上传一次轨迹)
     * 注意:当系统接口返回4001时(登录过期或失效),会重置retryTime。退出登录时也会重置。</p>
     */
    private BDAbstractLocationListener myLocationListener = new BDAbstractLocationListener() {

        @Override
        public void onReceiveLocation(BDLocation location) {
            long cTime = System.currentTimeMillis();
            LogUtil.e("myLocationListener= " + cTime);
            if ((cTime-lastLocTime)<1000){
                return;
            }
            lastLocTime = System.currentTimeMillis();
            if (location == null) {
                if (BaseConstant.LOGING)
                    FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                            getString(R.string.tip23), true);
                return;
            }else {
                if (location.getLatitude() == 0 && location.getLongitude() == 0){
                    OptionUtil.addToast(baseApplication, getString(R.string.tip23));
                    if (BaseConstant.LOGING)
                        FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                                " 定位失败：经度=" + location.getLongitude() + " 纬度=" + location.getLatitude(), true);
                    return;
                }else if (location.getLatitude() == 4.9E-324 && location.getLongitude() == 4.9E-324){
                    OptionUtil.addToast(baseApplication, getString(R.string.tip23));

                    if (BaseConstant.LOGING)
                        FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                                " 定位失败：经度=" + location.getLongitude() + " 纬度=" + location.getLatitude(), true);
                    return;
                }else if(location.getLocType()==BDLocation.TypeServerError||location.getLocType()==BDLocation.TypeNetWorkException||location.getLocType()==BDLocation.TypeCriteriaException){
                    OptionUtil.addToast(baseApplication, "网络不通,定位失败");
                    /*OrderConditionEntity orderConditionEntity=new OrderConditionEntity();
                    orderConditionEntity.setOrderId(SharedUtil.getLocalOrder(getBaseContext()));
                    orderConditionEntity.setTime(TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss"));
                    orderConditionEntity.setType("6");
                    orderConditionEntity.setAddress(SharedUtil.getAddress(getBaseContext()));
                    orderConditionEntity.setLat(SharedUtil.getLat(getBaseContext()));
                    orderConditionEntity.setLng(SharedUtil.getLng(getBaseContext()));*/
                }
            }
            try {
                String city = "";
                if (!StringUtil.isEmpty(location.getAddress().city)) {
                    city = location.getAddress().city;
                }
                String addr = "";
                if (!StringUtil.isEmpty(location.getAddress().address)) {
                    addr = location.getAddress().address;
                }
                String coorType = location.getCoorType();
                String code = "";//查询城市编号
                LogUtil.e("city= " + city);
                SharedUtil.saveLocation(SaveBaseApplication19.this, location.getLatitude(),
                        location.getLongitude(), "" + city, "" + addr, "" + coorType, code);
            } catch (Exception e) {
                e.printStackTrace();
            }
            BroadcastUtil.sendLocLocationBroadcast(SaveBaseApplication19.this, location);
            LogUtil.e("isOutService2= " + isOutService);
            LogUtil.e("lastLocTime= "+lastLocTime);
            if (isOutService && localOrderEntity != null) {
                addLocation(location);
                long lastUploadTime = SharedUtil.getOrderTimer(baseApplication);
                if (lastUploadTime > 0) {
                    long currentTime = System.currentTimeMillis();
                    long interval = currentTime - lastUploadTime;
                    LogUtil.e("interval= "+interval);
                    LogUtil.e("currentTime= "+currentTime+" lastUploadTime= "+lastUploadTime+" getRetryTime= "+SharedUtil.getRetryTime(baseApplication));
                    if (interval >= SharedUtil.getRetryTime(baseApplication)) {
                        uploadTrack(false, localOrderEntity.order, false);
                    }
                }
            }else {
                if (BaseConstant.LOGING)
                    FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                            " 定位信息：经度=" + location.getLongitude() + " 纬度=" + location.getLatitude() + " 地址=" + location.getAddress().address, true);
            }

        }
    };


    //时钟管理器
    public void setAlarm() {
        alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        int alarmType = AlarmManager.RTC_WAKEUP;
        long timeOrLengthofWait = LOCTIME;
        String ALARM_ACTION = BaseConstant.ACTION_ALARM;
        long triggerAtTime = System.currentTimeMillis() + timeOrLengthofWait;
        Intent intentToFire = new Intent(ALARM_ACTION);
        pendingIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);
        cancelAlarm();
        alarms.set(alarmType, triggerAtTime, pendingIntent);
//        alarms.setRepeating(alarmType,triggerAtTime,timeOrLengthofWait, pendingIntent);
    }

    public void cancelAlarm() {
        try {
            alarms.cancel(pendingIntent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 开始轨迹采集
     */
    public void  startOut() {
        if (!StringUtil.isEmpty(SharedUtil.getLocalOrder(this))) {
            localOrderEntity = SharedUtil.getLocalOrderEntity(this);
            locationService = LocationService.getInstance(this);
            isOutService = true;
            lastLocTime = System.currentTimeMillis();

            int res = location(SaveBaseApplication19.LOCTIME);
            if (res==0){
                //启动定位成功
                OptionUtil.addToast(baseApplication, getString(R.string.track_bd_loc_success));
            }else {
                OptionUtil.addToast(baseApplication, getString(R.string.track_bd_loc_fail));
            }
            LogUtil.e("-----------start record latlng2------------");
//            setAlarm();
        }else {
            location(SaveBaseApplication19.LOCTIME);
        }
    }

    public void stopOut(boolean isQuitLogin) {
        isOutService = false;
        if (null != localOrderEntity && !isQuitLogin) {
            locationService.deleteByLocalId(localOrderEntity.order.schedId);
            localOrderEntity = null;
        }
        SharedUtil.saveLocalOrder(baseApplication, "");
        SharedUtil.saveOrderTimer(baseApplication, 0);
        SharedUtil.saveRetryTime(baseApplication,BaseConstant.UPLOAD_TRACK_NORMAL);
//        stopLocation();
//        cancelAlarm();
    }


    public boolean addLocation(BDLocation location) {
        LatLng preLatLng = queryPreLocation();
        String result = "0";
        String msg = "无";
        String locType = "" + location.getLocType();
        if (location.getRadius() < BaseConstant.LOCATION_RADIUS) {
            if (location.getLocType() == BDLocation.TypeGpsLocation || location.getLocType() ==
                    BDLocation.TypeNetWorkLocation || location.getLocType() == BDLocation
                    .TypeOffLineLocation) {// GPS定位结果,网络定位结果,离线定位结果
               /* OrderConditionEntity orderConditionEntity=new OrderConditionEntity();
                orderConditionEntity.setOrderId(SharedUtil.getLocalOrder(getBaseContext()));
                orderConditionEntity.setTime(TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss"));
                orderConditionEntity.setType("7");
                orderConditionEntity.setAddress(location.getAddrStr());
                orderConditionEntity.setLat(""+location.getLatitude());
                orderConditionEntity.setLng("" + location.getLongitude());*/
                GPSEntity gpsEntity = LocationUtil.gcj_To_Gps84(location.getLatitude(), location.getLongitude());
                double wgLat = gpsEntity.getWgLat();
                double wgLon = gpsEntity.getWgLon();
                double distance = DistanceUtil.getDistance(preLatLng, new LatLng(wgLat, wgLon));
                LogUtil.e("distance= "+distance);
                if (preLatLng.latitude == defaultLat && preLatLng.longitude == defaultLng) {
                    result = "1";
                } else {
                    if (distance > 5 && distance < 2000000) {//&&distance<200
                        result = "1";
                        //计算出起点圈，到终点圈，到终点圈然后出圈
                        if (localOrderEntity.schedOrderList!=null&&localOrderEntity.schedOrderList.size()>0){
                            for (int i=0;i<localOrderEntity.schedOrderList.size();i++){
                                dealArrive(localOrderEntity.schedOrderList.get(i),wgLat,wgLon);
                            }
                        }else {
                            dealArrive(localOrderEntity.order,wgLat,wgLon);
                        }
                    } else {
                        result = "2";
                    }

                }
            } else if (location.getLocType() == BDLocation.TypeServerError) {
                msg = "TypeServerError";
            } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                msg = "TypeNetWorkException";
            } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                msg = "TypeCriteriaException";
            }
        } else {
            msg = "定位精密度不足：" + location.getRadius();
        }
        if (result.equals("1")){
            if (BaseConstant.LOGING)
                FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间：" + TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") +
                        " 合理轨迹点--定位信息：经度=" + location.getLongitude() + " 纬度=" + location.getLatitude() + " 地址=" + location.getAddress().address+" 调度ID="+localOrderEntity.order.schedId, true);
        }
        saveLocation(location, result, msg, locType);
        if (BaseConstant.LOCATION_RADIUS > 60) {
            filterPoint();
        }
        if (result.equals("1")) {
            return true;
        } else {
            return false;
        }
    }

    private void dealArrive(OrderEntity entity,double wgLat,double wgLon){
        try {
            //运单状态修改前版本
            if (!entity.isStarted){
                double disStart = DistanceUtil.getDistance(new LatLng(Double.parseDouble(entity.startPlace.lat), Double.parseDouble(entity.startPlace.lon)),
                        new LatLng(wgLat, wgLon));
                //判断是否离开起点圈
                if (disStart>entity.startPlace.radius){
                    entity.isStarted = true;
                    SharedUtil.saveLocalOrder(baseApplication, localOrderEntity);
                }
            }else {
                if (!entity.isArrived){
                    double disArrive = DistanceUtil.getDistance(new LatLng(Double.parseDouble(entity.endPlace.lat), Double.parseDouble(entity.endPlace.lon)),
                            new LatLng(wgLat, wgLon));
                    //判断是否到达终点圈
                    if (disArrive<(entity.endPlace.radius)){
                        entity.isArrived = true;
                        SharedUtil.saveLocalOrder(baseApplication, localOrderEntity);
                        uploadTrack(false,entity,true);
                    }
                }else {
                    uploadTrack(false, entity, true);
                    if (!entity.isArrivedAndOut){
                        double disArrivedAndOut = DistanceUtil.getDistance(new LatLng(Double.parseDouble(entity.endPlace.lat), Double.parseDouble(entity.endPlace.lon)),
                                new LatLng(wgLat, wgLon));
                        //判断是否离开终点圈
                        if (disArrivedAndOut>entity.endPlace.radius){
                            entity.isArrivedAndOut = true;
                            SharedUtil.saveLocalOrder(baseApplication, localOrderEntity);
                        }
                    }else {

                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void saveLocation(BDLocation location, String result, String msg, String locType) {
        Double geoLat = location.getLatitude();// * 1E6
        Double geoLng = location.getLongitude();// * 1E6
        GPSEntity gpsEntity = LocationUtil.gcj_To_Gps84(geoLat, geoLng);
        double wgLat = gpsEntity.getWgLat();
        double wgLon = gpsEntity.getWgLon();
        String strLat = String.valueOf(wgLat);
        String strLon = String.valueOf(wgLon);
        if (strLat.length() > 13) {
            strLat = strLat.substring(0, 13);
        }
        if (strLon.length() > 13) {
            strLon = strLon.substring(0, 13);
        }

        LocationEntity locationEntity = new LocationEntity();
        locationEntity.setLat("" + strLat);
        locationEntity.setLng("" + strLon);
        locationEntity.setAddress("" + location.getAddrStr());
        locationEntity.setResult("" + result);
        locationEntity.setMsg("" + msg);
        locationEntity.setLocType("" + locType);
        locationEntity.setRadius(location.getRadius());
        locationEntity.setLocalId(localOrderEntity.order.schedId);
        locationEntity.setIsUploaded("0");
        locationService.insert(locationEntity);
    }

    /**
     * 到达签到成功后处理
     * @param order
     */
    public void dealArrivedSign(OrderEntity order){
        if (localOrderEntity!=null){
            boolean canStop = true;
            long arrivedTime = System.currentTimeMillis();
            localOrderEntity.order.arrivedTime = arrivedTime;
            localOrderEntity.order.isArrivedSign = true;
            localOrderEntity.order.isArrived = true;
            if (localOrderEntity.schedOrderList==null){
                SharedUtil.saveLocalOrder(baseApplication, localOrderEntity);
            }else {
                if (localOrderEntity.schedOrderList.size()<=1){
                    OrderEntity orderEntity = localOrderEntity.schedOrderList.get(0);
                    orderEntity.isArrivedSign = true;
                    orderEntity.arrivedTime = arrivedTime;
                    orderEntity.isArrived = true;
                    SharedUtil.saveLocalOrder(baseApplication, localOrderEntity);
                }else {

                    for (OrderEntity orderEntity:localOrderEntity.schedOrderList){
                        if (order.id.equals(orderEntity.id)){
                            orderEntity.isArrivedSign = true;
                            orderEntity.arrivedTime = arrivedTime;
                            orderEntity.isArrived = true;
                        }else {
                            if (orderEntity.signEnd!=null&&!StringUtil.isEmpty(orderEntity.signEnd.operateTime)){

                            }else {
                                if (!orderEntity.isArrivedSign){
                                    canStop = false;
                                }
                            }
                        }
                    }
                    SharedUtil.saveLocalOrder(baseApplication, localOrderEntity);

                }
            }
            if (canStop){
                SaveBaseApplication19.self().stopOut(false);
            }
        }
    }

    /**
     * 上传轨迹
     * @param showDialog
     * @param order
     */
    public void uploadTrack(boolean showDialog, final OrderEntity order, final boolean isArrived) {
        if (isArrived){
            //判断是否到达签到过
            if (order!=null&&order.isArrivedSign){
                return;
            }else if (order!=null&&order.signEnd!=null&&!StringUtil.isEmpty(order.signEnd.operateTime)){
                return;
            }
        }
        final List<LocationEntity> list = locationService.queryByOrderId(order.schedId);
        String latLng = "";
        for (LocationEntity locationEntity : list) {
            String item = locationEntity.lat + "," + locationEntity.lng + "," + TimeUtil
                    .formatServiceTime2(locationEntity.update_time) + "," + locationEntity.address;
            if (StringUtil.isEmpty(latLng)) {
                latLng = item;
            } else {
                latLng = latLng + "#" + item;
            }
            locationEntity.setIsUploaded("1");
        }
        //修改为自动到达签到 添加目的地为最后轨迹点
        if (isArrived){
            double lat = Double.parseDouble(order.endPlace.lat)+0.0011;
            double lng = Double.parseDouble(order.endPlace.lon)+0.0011;
            String strLat = String.valueOf(lat);
            String strLon = String.valueOf(lng);
            if (strLat.length()>13){
                strLat = strLat.substring(0,13);
            }
            if (strLon.length()>13){
                strLon = strLon.substring(0,13);
            }
            String item = ""+strLat+","+strLon+ "," + TimeUtil
                    .formatServiceTime2(""+System.currentTimeMillis()) + "," + order.endPlace.address;
            if (StringUtil.isEmpty(latLng)) {
                latLng = item;
            } else {
                latLng = latLng + "#" + item;
            }
        }
        if (StringUtil.isEmpty(latLng)){
//            OptionUtil.addToast(baseApplication,"当前没有需要上传的轨迹");
            if (isArrived){
                signForOrder(false,1,order);
            }
            return;
        }

        final Map<String, Object> argMap = HttpUtil.getEncryMap(this);
        argMap.put("tel", SharedUtil.getTel(this));
        argMap.put("orderId", order.id);
        argMap.put("latLon", latLng);
        ShowDialogTask task = new ShowDialogTask(this, "BaseApplication", null, getString(R
                .string.task3), showDialog, BaseConstant.UPLOAD_LATLNG, argMap, TaskConstant.POST);
        task.setShowTipSuccess(true);
        task.setiOnResultListener(new IOnResultListener() {
            @Override
            public void onOK(DispatchTask task) {
                locationService.update2Uploaded(list);
                SharedUtil.saveOrderTimer(baseApplication, System.currentTimeMillis());
                //重置重试时间间隔
                SharedUtil.saveRetryTime(baseApplication, BaseConstant.UPLOAD_TRACK_NORMAL);
//                OptionUtil.addToast(baseApplication,"更新轨迹成功！");
                if (isArrived){
                    signForOrder(false,1,order);
                }
                if (BaseConstant.LOGING)
                    FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间："+TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss")+" 轨迹提交记录成功：轨迹点=" +argMap.get("latLon")+" 手机号=" +argMap.get("tel")+" orderId=" +argMap.get("orderId"), true);
            }

            @Override
            public void onError(DispatchTask task) {
                //五分钟后重试
                SharedUtil.saveOrderTimer(baseApplication, System.currentTimeMillis());
                SharedUtil.saveRetryTime(baseApplication,BaseConstant.UPLOAD_TRACK_RETRY);
            }

            @Override
            public void onDone(DispatchTask task) {

            }
        });
        task.execute();
    }

    /**
     * 签到
     *
     * @param showDialog
     * @param type       类型：0是出发、1是到达
     */
    private void signForOrder(boolean showDialog, final int type, final OrderEntity order) {
        //判断是否到达签到过
        if (order!=null&&order.isArrivedSign){
            return;
        }else if (order!=null&&order.signEnd!=null&&!StringUtil.isEmpty(order.signEnd.operateTime)){
            return;
        }
        final Map<String, Object> argMap = HttpUtil.getEncryMap(this);
        argMap.put("tel", SharedUtil.getTel(this));
        argMap.put("orderId", order.id);
        if (type == 0) {
            argMap.put("type", "1");
            argMap.put("lat", SharedUtil.getLat(this));
            argMap.put("lon", SharedUtil.getLng(this));
            argMap.put("address", SharedUtil.getAddress(this));
        } else {
            argMap.put("type", "4");
            argMap.put("auto", "1");
            //修改为自动到达签到 添加目的地为签到点
            double lat = Double.parseDouble(order.endPlace.lat)+0.0011;
            double lng = Double.parseDouble(order.endPlace.lon)+0.0011;
            String strLat = String.valueOf(lat);
            String strLon = String.valueOf(lng);
            if (strLat.length()>13){
                strLat = strLat.substring(0,13);
            }
            if (strLon.length()>13){
                strLon = strLon.substring(0,13);
            }
            argMap.put("lat", ""+strLat);
            argMap.put("lon", ""+strLon);
            argMap.put("address", ""+SharedUtil.getAddress(this));

//            if ((order!=null&&order.isArrivedAndOut)||order.status==OptionUtil.ORDER_STATUS_4){
//                //到终点圈然后出圈 采用目标地址的经纬度116.401578,39.903973
//                //平台设为已到达后，app可以到达签到，采用目标地址的经纬度116.40143,39.904309
////                LogUtil.e("localOrderData.isArrivedAndOut="+localOrderData.isArrivedAndOut);
//                double lat = Double.parseDouble(order.endPlace.lat)+0.001;
//                double lng = Double.parseDouble(order.endPlace.lon)+0.001;
//                String strLat = String.valueOf(lat);
//                String strLon = String.valueOf(lng);
//                if (strLat.length()>13){
//                    strLat = strLat.substring(0,13);
//                }
//                if (strLon.length()>13){
//                    strLon = strLon.substring(0,13);
//                }
//                argMap.put("lat", ""+strLat);
//                argMap.put("lon", ""+strLon);
//                argMap.put("address", ""+order.endPlace.address);
//            }else {
//                //到达签到采用轨迹最后一个点
//                List<LocationEntity> locationEntityList = locationService.queryByOrderId(order.schedId,false);
//                if (locationEntityList!=null&&locationEntityList.size()>0){
//                    long ct = System.currentTimeMillis();
//                    long lt = Long.parseLong(locationEntityList.get(0).getCreate_time());
//                    if ((ct-lt)>600000){
//                        OptionUtil.addToast(baseApplication,"最后定位点在10分钟之前，正在重新定位，预计需要1分钟");
//                        return;
//                    }
//                    argMap.put("lat", locationEntityList.get(0).getLat());
//                    argMap.put("lon", locationEntityList.get(0).getLng());
//                    argMap.put("address", locationEntityList.get(0).getAddress());
//                }else {
//                    OptionUtil.addToast(baseApplication,"轨迹不全，稍后重试");
//                    return;
//                }
//            }

        }
        ShowDialogTask task = new ShowDialogTask(this, "BaseApplication", null, getString(R.string
                .task3), showDialog, BaseConstant.ORDER_SIGN, argMap, TaskConstant.POST);
        task.setiOnResultListener(new IOnResultListener() {
            @Override
            public void onOK(DispatchTask task) {
                if (type == 0) {

                } else {
                    dealArrivedSign(order);
                }
                if (BaseConstant.LOGING)
                    FileUtil.writeFile(BaseConstant.LOGPATH, "\n时间："+TimeUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss")+" 自动到达签到提交记录成功：经度=" +argMap.get("lon")+" 纬度=" +argMap.get("lat")+" orderId=" +argMap.get("orderId"), true);
                BroadcastUtil.sendOrderRefreshBroadcast(baseApplication);
            }

            @Override
            public void onError(DispatchTask task) {

            }

            @Override
            public void onDone(DispatchTask task) {

            }
        });
        task.execute();
    }

    /**
     * 查询最后一个定位点
     *
     * @return
     */
    LatLng queryPreLocation() {
        LatLng latLng = null;
        List<LocationEntity> locationEntityList = locationService.query(localOrderEntity.order.schedId);
        if (locationEntityList != null && locationEntityList.size() > 0) {
            latLng = new LatLng(Double.parseDouble(locationEntityList.get(locationEntityList.size
                    () - 1).lat), Double.parseDouble(locationEntityList.get(locationEntityList
                    .size() - 1).lng));
        } else {
            latLng = new LatLng(defaultLat, defaultLng);
        }
        return latLng;
    }

    /**
     * 筛选定位点
     */
    void filterPoint() {
        List<LocationEntity> locationEntityList = locationService.queryLimit(localOrderEntity.order.schedId, null);
        if (locationEntityList != null && locationEntityList.size() == 4) {
            List<LocationEntity> filterList = redecePoints(locationEntityList);
            for (LocationEntity entity : locationEntityList) {
                boolean save = false;
                for (LocationEntity filter : filterList) {
                    if (entity.getId().equals(filter.getId())) {
                        save = true;
                    }
                }
                if (!save) {
                    if (entity.getResult().equals("1")) {
                        entity.setResult("5");
                        locationService.update(entity);
                    }
                }
            }
        }
    }


    private double calcAngle(double lat_a, double lng_a, double lat_b, double lng_b) {
        double d = 0;
        lat_a = lat_a * Math.PI / 180;
        lng_a = lng_a * Math.PI / 180;
        lat_b = lat_b * Math.PI / 180;
        lng_b = lng_b * Math.PI / 180;

        d = Math.sin(lat_a) * Math.sin(lat_b) + Math.cos(lat_a) * Math.cos(lat_b) * Math.cos
                (lng_b - lng_a);
        d = Math.sqrt(1 - d * d);
        d = Math.cos(lat_b) * Math.sin(lng_b - lng_a) / d;
        d = Math.asin(d) * 180 / Math.PI;
        return d;
    }

    private double calAngle(double startLat, double startLng, double midLat, double midLng,
                            double endLat, double endLng) {
        double angle1 = calcAngle(midLng * 3600000.0, midLat * 3600000.0, startLng * 3600000.0,
                startLat * 3600000.0);
        double angle2 = calcAngle(midLng * 3600000.0, midLat * 3600000.0, endLng * 3600000.0,
                endLat * 3600000.0);
        double angle = Math.abs(angle1 - angle2);

        if (angle <= 180) {
            return angle;
        } else
            return 360 - angle;
    }

    //通过计算连续两个夹角和两点距离来去除无效轨迹点
    //两点距离大于20m则两点距离有效，两个夹角分别小于60、80则去除中间两点
    //参数testArr为原始数据，包含经纬度信息
    List<LocationEntity> redecePoints(List<LocationEntity> testArr) {
        List<LocationEntity> test1Arr = new ArrayList<LocationEntity>();
        if (testArr.size() < 4) {
            return testArr;
        } else {
            for (int n = 0; n < (testArr.size() - 3); n++) {
                double distance = DistanceUtil.getDistance(new LatLng(testArr.get(n + 1)
                                .getLatDouble(), testArr.get(n + 1).getLngDouble()),
                        new LatLng(testArr.get(n + 2).getLatDouble(), testArr.get(n + 2)
                                .getLngDouble()));
                //2,3两点间距离大于20m则将1，2两点放入新数组，3、4点做下次比较
                if (distance > 20) {
                    test1Arr.add(testArr.get(n));
                    test1Arr.add(testArr.get(n + 1));

                    //尾点保留
                    if (n == testArr.size() - 4) {
                        test1Arr.add(testArr.get(n + 2));
                        test1Arr.add(testArr.get(n + 3));
                    }
                    //校准索引
                    n++;
                } else {
                    double angle1 = calAngle(testArr.get(n).getLatDouble(), testArr.get(n)
                            .getLngDouble(), testArr.get(n + 1).getLatDouble(), testArr.get(n +
                            1).getLngDouble(), testArr.get(n + 2).getLatDouble(), testArr.get(n +
                            2).getLngDouble());
                    //1,2,3三点角度大于60则将1，2两点放入新数组，3、4点做下次比较
                    if (angle1 > 60) {
                        test1Arr.add(testArr.get(n));
                        test1Arr.add(testArr.get(n + 1));

                        //尾点保留
                        if (n == testArr.size() - 4) {
                            test1Arr.add(testArr.get(n + 2));
                            test1Arr.add(testArr.get(n + 3));
                        }
                        n++;
                    } else {
                        double angle2 = calAngle(testArr.get(n + 1).getLatDouble(), testArr.get(n
                                        + 1).getLngDouble(), testArr.get(n + 2).getLatDouble(),
                                testArr
                                        .get(n + 2).getLngDouble(), testArr.get(n + 3)
                                        .getLatDouble(),
                                testArr.get(n + 3).getLngDouble());
                        //2,3,4三点角度大于80则将1，2两点放入新数组，3、4点做下次比较
                        if (angle2 > 80) {
                            test1Arr.add(testArr.get(n));
                            test1Arr.add(testArr.get(n + 1));

                            //尾点保留
                            if (n == testArr.size() - 4) {
                                test1Arr.add(testArr.get(n + 2));
                                test1Arr.add(testArr.get(n + 3));
                            }
                            n++;
                        }
                        //否则去掉中间两点
                        else {
                            test1Arr.add(testArr.get(n + 3));
                            n += 3;
                        }
                    }
                }
            }
            return test1Arr;
        }
    }
}